package cn.ylz.ylmall.order.service.impl;


import cn.ylz.ylmall.common.ex.ServiceException;
import cn.ylz.ylmall.common.util.OrderCodeFactory;
import cn.ylz.ylmall.common.util.QRCodeGenerator;
import cn.ylz.ylmall.common.web.OrderCode;
import cn.ylz.ylmall.common.web.ServiceCode;
import cn.ylz.ylmall.order.dao.persist.mapper.OrderItemMapper;
import cn.ylz.ylmall.order.dao.persist.repository.OrderDetailRepository;
import cn.ylz.ylmall.order.dao.persist.repository.OrderItemRepository;
import cn.ylz.ylmall.order.pojo.entity.OrderDetail;
import cn.ylz.ylmall.order.pojo.entity.OrderItem;
import cn.ylz.ylmall.order.pojo.request.OrderCreateReq;
import cn.ylz.ylmall.order.pojo.request.SingleOrderReq;
import cn.ylz.ylmall.order.pojo.vo.OrderItemImgVO;
import cn.ylz.ylmall.order.pojo.vo.OrderItemVO;
import cn.ylz.ylmall.order.pojo.vo.OrderDetailVO;
import cn.ylz.ylmall.shopping.dao.persist.repository.IShoppingRepository;
import cn.ylz.ylmall.shopping.pojo.vo.ShoppingVO;
import cn.ylz.ylmall.order.service.OrderDetailService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.google.zxing.WriterException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.io.File;
import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.*;


/**
* @author ks
* @description 针对表【order(订单表)】的数据库操作Service实现
* @createDate 2023-08-10 10:10:20
*/
@Slf4j
@Service
public class OrderDetailServiceImpl implements OrderDetailService {

    @Autowired
    private OrderDetailRepository orderDetailRepository;

    @Autowired
    private OrderItemMapper orderItemMapper;

    @Autowired
    private IShoppingRepository iShoppingRepository;

    @Autowired
    private OrderItemRepository orderItemRepository;

    private static final String ip = "127.0.0.1";

    /**
     * 新增订单
     * @param orderCreateReq
     * @param userId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<String> insertOrder(OrderCreateReq orderCreateReq, Long userId) {

        //获取用户的购物车
        List<ShoppingVO> shoppingVOList = iShoppingRepository.showAll(userId);

        System.out.println("用户购物车" + shoppingVOList);

        //从购物车中选出用户要购买的商品
        ArrayList<ShoppingVO> shoppingArrayList = new ArrayList<ShoppingVO>();
        for (int i = 0; i < shoppingVOList.size(); i++) {
            ShoppingVO shoppingVO = shoppingVOList.get(i);
            if (shoppingVO.getSelected() == 1) {
                shoppingArrayList.add(shoppingVO);
            }
        }

        shoppingVOList = shoppingArrayList;

        System.out.println("要购买的商品" + shoppingVOList);

        if (CollectionUtils.isEmpty(shoppingVOList)) {
            throw new ServiceException(ServiceCode.ERROR_CART_EMPTY, "购物车为空");
        }

        //判断库存是否可以正常使用
        validSaleStatusAndStock(shoppingVOList);

        //把【查询购物车表Shopping表，获得的商品数据】转化为【能够存储到order_item表的、商品数据】
        List<OrderItem> orderItemsList = shoppingVOTOOrderItemList(shoppingVOList);

        //扣库存,进行到这步证明了库存是正常的
        for (int i = 0; i < orderItemsList.size(); i++) {
            OrderItem orderItem = orderItemsList.get(i);
            int stock = orderItemMapper.selectProductStock(orderItem.getProductId()) - orderItem.getQuantity();
            orderItemMapper.updateProductStock(orderItem.getProductId(), stock);
        }

        //将下单后的商品从购物车中删除
        cleanCart(shoppingVOList);

        //设置列表传回订单
        List<String> orderNumList =new ArrayList<>();
        //循环将每一个购物车中的商品赋给一个订单
        for (int i = 0; i < orderItemsList.size(); i++) {

            String orderNum = OrderCodeFactory.getOrderCode(userId);

            OrderDetail orderDetail = new OrderDetail();
            //设置userid
            orderDetail.setUserId(userId);
            //名字.地址,电话
            BeanUtils.copyProperties(orderCreateReq, orderDetail);
            //设置订单号
            orderDetail.setOrderNo(orderNum);
            //设置订单总价
            orderDetail.setTotalPrice(totalPrice(orderItemsList));
            //设置订单状态未付款
            orderDetail.setOrderStatus(1);
            //设置运费
            orderDetail.setPostage(BigDecimal.valueOf(0));
            //支付方式
            orderDetail.setPaymentType(1);
            orderDetail.setCreateTime(new Date());
            orderDetail.setUpdateTime(orderDetail.getCreateTime());
            //生成订单
            orderDetailRepository.insert(orderDetail);

            //把订单中的每种商品，写到order_item表中
            OrderItem orderItem = orderItemsList.get(i);
            System.out.println("第 " + i + "个商品数据 : " + orderItem);
            orderItem.setOrderNo(orderNum);
            orderItem.setCreateTime(new Date());
            orderItem.setUpdateTime(orderItem.getCreateTime());
            orderItemRepository.insert(orderItem);

            orderNumList.add(orderNum);
        }

        return orderNumList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createdSingleOrder(SingleOrderReq singleOrderReq,Long userId) {


        if (singleOrderReq.getQuantity() > orderItemMapper.selectProductStock(singleOrderReq.getProductId())) {
            throw new ServiceException(ServiceCode.ERROR_PRODUCT_INSUFFICIENT, "商品库存不足");
        }

        String orderNum = OrderCodeFactory.getOrderCode(userId);

        OrderDetail orderDetail = new OrderDetail();
        //设置userid
        orderDetail.setUserId(userId);
        //名字.地址,电话
        orderDetail.setReceiverName(singleOrderReq.getReceiverName());
        orderDetail.setReceiverAddress(singleOrderReq.getReceiverAddress());
        orderDetail.setReceiverMobile(singleOrderReq.getReceiverMobile());
        //设置订单号
        orderDetail.setOrderNo(orderNum);
        //设置订单总价
        orderDetail.setTotalPrice(singleOrderReq.getTotalPrice());
        //设置订单状态未付款
        orderDetail.setOrderStatus(1);
        //设置运费
        orderDetail.setPostage(BigDecimal.valueOf(0));
        //支付方式
        orderDetail.setPaymentType(1);
        orderDetail.setCreateTime(new Date());
        orderDetail.setUpdateTime(orderDetail.getCreateTime());
        //生成订单
        orderDetailRepository.insert(orderDetail);

        OrderItem orderItem = new OrderItem();
        orderItem.setOrderNo(orderNum);
        orderItem.setCreateTime(new Date());
        orderItem.setUpdateTime(orderItem.getCreateTime());

        orderItem.setProductId(singleOrderReq.getProductId());
        orderItem.setProductName(singleOrderReq.getProductName());
        orderItem.setProductImg(singleOrderReq.getProductImg());
        orderItem.setUnitPrice(singleOrderReq.getUnitPrice());
        orderItem.setTotalPrice(singleOrderReq.getTotalPrice());
        orderItem.setQuantity(singleOrderReq.getQuantity());

        orderItemRepository.insert(orderItem);

        //扣除库存
        int stock = orderItemMapper.selectProductStock(orderItem.getProductId()) - orderItem.getQuantity();
        orderItemMapper.updateProductStock(orderItem.getProductId(), stock);

        return orderNum;
    }

    /**
     * 查询订单详情
     *
     * @param orderNo
     * @param userId
     * @return
     */
    @Override
    public OrderDetailVO selectOrder(String orderNo, Long userId) {
        OrderDetail orderDetail = orderDetailRepository.selectOrderVO(orderNo);

        //判断订单是否存在
        if (orderDetail == null) {
            throw new ServiceException(ServiceCode.ERROR_ORDER_EXIST, "订单不存在");
        }

        //判断订单是否是当前用户
        if (!orderDetail.getUserId().equals(userId)) {
            throw new ServiceException(ServiceCode.ERROR_ORDER_MISMATCH, "订单不匹配");
        }

        return orderDetailToOrderDetailVO(orderDetail);
    }

    /**
     * 删除订单
     *
     * @param orderNo
     * @param userId
     * @return
     */
    @Override
    public int deleteOrder(String orderNo, Long userId) {
        OrderDetail orderDetail = orderDetailRepository.selectOrderVO(orderNo);

        //判断订单是否存在
        if (orderDetail == null) {
            throw new ServiceException(ServiceCode.ERROR_ORDER_EXIST, "订单不存在");
        }

        //判断订单是否是当前用户
        if (!orderDetail.getUserId().equals(userId)) {
            throw new ServiceException(ServiceCode.ERROR_ORDER_MISMATCH, "订单不匹配");
        }

        return orderDetailRepository.deleteOrder(orderNo);
    }

    /**
     * 分页查询订单
     * @param userId
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo selectOrderList(Long userId, Integer pageNum, Integer pageSize) {

        //设置mybatis查询参数
        QueryWrapper<OrderDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);

        //查询订单列表
        List<OrderDetail> orderDetailList = orderDetailRepository.selectOrderList(queryWrapper);
        //将查到的订单转换为订单VO
        List<OrderDetailVO> orderDetailVOList = orderDetailListToOrderDetailVOList(orderDetailList);

        //设置分页的当前页和每页的数量
        PageHelper.startPage(pageNum,pageSize);
        PageInfo pageInfo = new PageInfo(orderDetailList);
        pageInfo.setList(orderDetailVOList);
        return pageInfo;
    }

    /**
     * 修改订单
     * @param orderDetail
     * @param userId
     * @return
     */
    @Override
    public int updateOrder(OrderDetail orderDetail, Long userId) {
        String orderNo = orderDetail.getOrderNo();

        Map<String, Object> paramMap = new HashMap<>(10);
        paramMap.put("orderDetail", orderDetail);

        return orderDetailRepository.updateOrder(paramMap);
    }

    /**
     * 获取订单二维码
     * @param orderNo
     * @return
     */
    @Override
    public String getQrCode(String orderNo) {
        //首先，因为这儿是非Controller，所以，通过RequestContextHolder获取HttpServletRequest；
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        //然后，拼凑订单支付url的一部分：“127.0.0.1:8083”;
        String address = ip + ":" + request.getLocalPort();
        //然后，完整拼凑订单支付url：“http://127.0.0.1:8083//pay?orderNo=订单号”;
        //这个就是将要写到二维码中的信息；其实，也是后面的【前台：支付订单】接口的，附带了orderNo参数的完整url
        String payUrl = "http://" + address + "//v1/Order/qrcode?orderNo=" + orderNo;


        File directory = new File("D:\\qrCode\\");
        if (!directory.exists()) {
            directory.mkdirs();
        }

        String filePath = directory.getAbsolutePath() + "\\" + orderNo + ".png";
        System.out.println(filePath);

        try {
            QRCodeGenerator.generateQRCode(payUrl, 350, 350, filePath);
        } catch (WriterException | IOException e) {
            e.printStackTrace();
        }

        //获取二维码图片的访问地址；（PS：e仅仅是访问地址，而是访问地址）
        String pngAddress = "http://" + address + "/images/" + orderNo + ".png";
        //然后，把这个二维码图片的访问地址返回；
        return pngAddress;
    }

    @Override
    public PageInfo<OrderDetailVO> selectOrderStatus(Integer orderStatus, Integer pageNum, Integer pageSize) {
        //设置mybatis查询参数
        QueryWrapper<OrderDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_status", orderStatus);

        //查询订单列表
        List<OrderDetail> orderDetailList = orderDetailRepository.selectOrderList(queryWrapper);
        //将查到的订单转换为订单VO
        List<OrderDetailVO> orderDetailVOList = orderDetailListToOrderDetailVOList(orderDetailList);

        //设置分页的当前页和每页的数量
        PageHelper.startPage(pageNum,pageSize);
        PageInfo pageInfo = new PageInfo(orderDetailList);
        pageInfo.setList(orderDetailVOList);
        return pageInfo;
    }

    @Override
    public int cancelOrder(Long userId, String orderNo) {
        OrderDetail orderDetail = orderDetailRepository.selectOrderVO(orderNo);

        //判断订单是否存在
        if (orderDetail == null) {
            throw new ServiceException(ServiceCode.ERROR_ORDER_EXIST, "订单不存在");
        }

        //判断订单是否是当前用户
        if (!orderDetail.getUserId().equals(userId)) {
            throw new ServiceException(ServiceCode.ERROR_ORDER_MISMATCH, "订单不匹配");
        }

        //当订单未付款时，用户才可以将订单取消
        if(orderDetail.getOrderStatus().equals(OrderCode.ORDER_NOTPAY.getCode())){

            orderDetail.setOrderStatus(OrderCode.ORDER_CANCELLED.getCode());
            //订单被取消,说明该订单已完结
            orderDetail.setEndTime(new Date());

            Map<String, Object> cancelMap = new HashMap<>(10);
            cancelMap.put("orderDetail", orderDetail);

            return orderDetailRepository.updateOrder(cancelMap);
        }else {
            throw new ServiceException(ServiceCode.ERROR_ORDER_STATUS,"订单当前状态不允许取消");
        }

    }

    @Override
    public int payOrder(String orderNo) {
        OrderDetail orderDetail = orderDetailRepository.selectOrderVO(orderNo);

        //判断订单是否存在
        if (orderDetail == null) {
            throw new ServiceException(ServiceCode.ERROR_ORDER_EXIST, "订单不存在");
        }

        //当订单未付款时
        if(orderDetail.getOrderStatus().equals(OrderCode.ORDER_NOTPAY.getCode())){

            orderDetail.setOrderStatus(OrderCode.ORDER_PAID.getCode());

            orderDetail.setPayTime(new Date());

            Map<String, Object> cancelMap = new HashMap<>(10);
            cancelMap.put("orderDetail", orderDetail);

            return orderDetailRepository.updateOrder(cancelMap);
        }else {
            throw new ServiceException(ServiceCode.ERROR_ORDER_STATUS,"订单当前状态不允许取消");
        }
    }


    /**
     * 将orderDetail转换为orderDetailVO
     * @param orderDetail
     * @return OrderDetailVO
     */
    private OrderDetailVO orderDetailToOrderDetailVO(OrderDetail orderDetail) {

        OrderDetailVO orderDetailVO = new OrderDetailVO();

        BeanUtils.copyProperties(orderDetail, orderDetailVO);

        //查询商品详情
        OrderItem orderItem = orderItemMapper.selectByOrderNo(orderDetail.getOrderNo());

        Gson gson = new Gson();
        Type type = new TypeToken<List<String>>() {}.getType();
        List<String> imageUrls = gson.fromJson(orderItem.getProductImg(), type);

        OrderItemImgVO orderItemImgVO = new OrderItemImgVO();
        //用OrderItem给OrderItemImgVO赋值
        BeanUtils.copyProperties(orderItem, orderItemImgVO);

        orderItemImgVO.setProductImgs(imageUrls);

        orderDetailVO.setOrderItemImgVO(orderItemImgVO);

        Integer orderStatus = orderDetailVO.getOrderStatus();

        String orderStatusName = OrderCode.findEnumByCode(orderStatus).getName();

        orderDetailVO.setOrderStatusName(orderStatusName);

        return orderDetailVO;
    }

    /**
     * 将orderDetailList转换为orderDetailVOList
     * @param orderDetailList
     * @return OrderDetailVO
     */
    private List<OrderDetailVO> orderDetailListToOrderDetailVOList(List<OrderDetail> orderDetailList) {
        List<OrderDetailVO> orderVOList = new ArrayList<>();
        for (int i = 0; i < orderDetailList.size(); i++) {
            OrderDetail orderDetail = orderDetailList.get(i);
            //调用getOrderVO()方法，把每个Order拼装成OrderVO
            OrderDetailVO orderDetailVO = orderDetailToOrderDetailVO(orderDetail);
            orderVOList.add(orderDetailVO);
        }
        return orderVOList;
    }


    private void validSaleStatusAndStock(List<ShoppingVO> shoppingVOList) {
        for (int i = 0; i < shoppingVOList.size(); i++) {
            ShoppingVO shoppingVO = shoppingVOList.get(i);
            //判断商品库存是否足够
            if (shoppingVO.getQuantity() > orderItemMapper.selectProductStock(shoppingVO.getProductId())) {
                throw new ServiceException(ServiceCode.ERROR_PRODUCT_INSUFFICIENT, "商品库存不足");
            }
        }
    }

    private List<OrderItem> shoppingVOTOOrderItemList(List<ShoppingVO> shoppingList) {
        List<OrderItem> orderItemList = new ArrayList<>();
        for (int i = 0; i < shoppingList.size(); i++) {
            ShoppingVO shoppingVO = shoppingList.get(i);
            OrderItem orderItem = new OrderItem();
            //商品id
            orderItem.setProductId(shoppingVO.getProductId());
            //商品名字
            orderItem.setProductName(shoppingVO.getProductName());
            //商品图片
            orderItem.setProductImg(shoppingVO.getImageUrls());
            //商品单价
            orderItem.setUnitPrice(shoppingVO.getPrice());
            //商品数量
            orderItem.setQuantity(shoppingVO.getQuantity());
            //该商品的总价
            orderItem.setTotalPrice(shoppingVO.getTotalPrice());

            orderItemList.add(orderItem);

        }
        return orderItemList;
    }

    private void cleanCart(List<ShoppingVO> shoppingVOList) {
        for (int i = 0; i < shoppingVOList.size(); i++) {
            ShoppingVO shoppingVO = shoppingVOList.get(i);
            iShoppingRepository.updateNumber(shoppingVO.getCartId());
        }
    }

    private BigDecimal totalPrice(List<OrderItem> orderItemList) {
        System.out.println("orderItemList:" + orderItemList);
        BigDecimal totalPrice = BigDecimal.valueOf(0);
        for (int i = 0; i < orderItemList.size(); i++) {
            OrderItem orderItem = orderItemList.get(i);
            totalPrice = totalPrice.add(orderItem.getTotalPrice());
        }
        System.out.println("totalPrice " + totalPrice);
        return totalPrice;
    }
}


